package com.rickpan.service;

import com.rickpan.entity.TeamKey;
import com.rickpan.entity.User;
import com.rickpan.repository.TeamKeyRepository;
import com.rickpan.repository.UserRepository;
import com.rickpan.dto.response.TeamKeyDTO;
import com.rickpan.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 团队密钥服务实现类
 * 
 * @author RickPan Team
 * @since 2025-07-19
 */
@Service
@Transactional
public class TeamKeyService {

    private static final Logger logger = LoggerFactory.getLogger(TeamKeyService.class);

    // 密钥算法配置
    private static final String KEY_ALGORITHM = "AES";
    private static final int KEY_LENGTH = 256;
    private static final String ENCRYPTION_ALGORITHM = "AES-256-GCM";
    
    // 密钥过期时间（默认90天）
    private static final long DEFAULT_KEY_EXPIRY_DAYS = 90;

    @Autowired
    private TeamKeyRepository teamKeyRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TeamMemberService teamMemberService;

    /**
     * 获取团队当前活跃密钥
     */
    public TeamKeyDTO getCurrentTeamKey(Long teamId, Long userId) {
        logger.info("🔑 获取团队当前密钥: teamId={}, userId={}", teamId, userId);

        try {
            // 验证用户是否为团队成员
            logger.info("🔍 检查用户是否为团队成员: teamId={}, userId={}", teamId, userId);
            boolean isMember = teamMemberService.isTeamMember(teamId, userId);
            logger.info("🔍 团队成员检查结果: {}", isMember);

            if (!isMember) {
                logger.warn("⚠️ 用户不是团队成员: teamId={}, userId={}", teamId, userId);
                throw new BusinessException("您不是该团队成员，无法获取密钥");
            }
        } catch (Exception e) {
            logger.error("❌ 团队成员检查失败: teamId={}, userId={}, error={}", teamId, userId, e.getMessage(), e);
            throw new BusinessException("团队成员验证失败: " + e.getMessage());
        }

        logger.info("🔍 查询团队密钥: teamId={}", teamId);
        Optional<TeamKey> keyOpt = teamKeyRepository.findCurrentActiveKey(teamId);
        logger.info("🔍 密钥查询结果: {}", keyOpt.isPresent() ? "找到密钥" : "未找到密钥");

        if (keyOpt.isEmpty()) {
            logger.warn("⚠️ 团队密钥不存在，尝试初始化: teamId={}", teamId);
            // 自动初始化团队密钥
            return initializeTeamKey(teamId, userId);
        }

        TeamKey teamKey = keyOpt.get();
        
        // 检查密钥是否过期
        if (isKeyExpired(teamKey)) {
            logger.warn("⚠️ 团队密钥已过期，自动轮换: teamId={}, keyVersion={}", teamId, teamKey.getKeyVersion());
            return rotateTeamKey(teamId, userId);
        }

        logger.info("✅ 成功获取团队当前密钥: teamId={}, keyVersion={}", teamId, teamKey.getKeyVersion());
        return convertToDTO(teamKey);
    }

    /**
     * 获取团队指定版本的密钥
     */
    public TeamKeyDTO getTeamKeyByVersion(Long teamId, Integer keyVersion, Long userId) {
        logger.info("🔑 获取团队指定版本密钥: teamId={}, keyVersion={}, userId={}", teamId, keyVersion, userId);

        // 验证用户是否为团队成员
        if (!teamMemberService.isTeamMember(teamId, userId)) {
            throw new BusinessException("您不是该团队成员，无法获取密钥");
        }

        Optional<TeamKey> keyOpt = teamKeyRepository.findByTeamIdAndKeyVersion(teamId, keyVersion);
        
        if (keyOpt.isEmpty()) {
            throw new BusinessException("指定版本的密钥不存在");
        }

        TeamKey teamKey = keyOpt.get();
        
        // 只允许获取活跃状态的密钥
        if (teamKey.getStatus() != TeamKey.KeyStatus.active) {
            throw new BusinessException("该版本密钥已失效");
        }

        logger.info("✅ 成功获取指定版本密钥: teamId={}, keyVersion={}", teamId, keyVersion);
        return convertToDTO(teamKey);
    }

    /**
     * 初始化团队密钥
     */
    public TeamKeyDTO initializeTeamKey(Long teamId, Long userId) {
        logger.info("🚀 初始化团队密钥: teamId={}, userId={}", teamId, userId);

        // 验证用户是否为团队成员
        if (!teamMemberService.isTeamMember(teamId, userId)) {
            throw new BusinessException("您不是该团队成员，无法初始化密钥");
        }

        // 检查是否已存在密钥
        Optional<TeamKey> existingKey = teamKeyRepository.findCurrentActiveKey(teamId);
        if (existingKey.isPresent()) {
            logger.info("✅ 团队密钥已存在，返回现有密钥: teamId={}, keyVersion={}", teamId, existingKey.get().getKeyVersion());
            return convertToDTO(existingKey.get());
        }

        // 生成新密钥
        String encryptedKey = generateSecureKey();
        
        // 创建密钥记录
        TeamKey teamKey = new TeamKey();
        teamKey.setTeamId(teamId);
        teamKey.setKeyVersion(1); // 初始版本
        teamKey.setEncryptedKey(encryptedKey);
        teamKey.setAlgorithm(ENCRYPTION_ALGORITHM);
        teamKey.setKeyLength(KEY_LENGTH);
        teamKey.setStatus(TeamKey.KeyStatus.active);
        teamKey.setCreatedBy(userId);
        teamKey.setExpiresAt(LocalDateTime.now().plusDays(DEFAULT_KEY_EXPIRY_DAYS));

        TeamKey savedKey = teamKeyRepository.save(teamKey);

        logger.info("✅ 团队密钥初始化成功: teamId={}, keyVersion={}", teamId, savedKey.getKeyVersion());
        return convertToDTO(savedKey);
    }

    /**
     * 轮换团队密钥
     */
    public TeamKeyDTO rotateTeamKey(Long teamId, Long userId) {
        logger.info("🔄 开始轮换团队密钥: teamId={}, userId={}", teamId, userId);

        // 验证用户是否为团队成员
        if (!teamMemberService.isTeamMember(teamId, userId)) {
            throw new BusinessException("您不是该团队成员，无法轮换密钥");
        }

        // 获取当前最大版本号
        Integer maxVersion = teamKeyRepository.findMaxKeyVersion(teamId);
        Integer newVersion = (maxVersion == null ? 0 : maxVersion) + 1;

        // 生成新密钥
        String encryptedKey = generateSecureKey();

        // 创建新版本密钥
        TeamKey newTeamKey = new TeamKey();
        newTeamKey.setTeamId(teamId);
        newTeamKey.setKeyVersion(newVersion);
        newTeamKey.setEncryptedKey(encryptedKey);
        newTeamKey.setAlgorithm(ENCRYPTION_ALGORITHM);
        newTeamKey.setKeyLength(KEY_LENGTH);
        newTeamKey.setStatus(TeamKey.KeyStatus.active);
        newTeamKey.setCreatedBy(userId);
        newTeamKey.setExpiresAt(LocalDateTime.now().plusDays(DEFAULT_KEY_EXPIRY_DAYS));

        TeamKey savedKey = teamKeyRepository.save(newTeamKey);

        // 可选：撤销旧版本密钥（保留最近2个版本）
        if (newVersion > 2) {
            int revokedCount = teamKeyRepository.revokeOldKeys(teamId, newVersion - 1);
            logger.info("📝 撤销旧版本密钥: teamId={}, revokedCount={}", teamId, revokedCount);
        }

        logger.info("✅ 团队密钥轮换成功: teamId={}, newKeyVersion={}", teamId, newVersion);
        return convertToDTO(savedKey);
    }

    /**
     * 获取密钥健康状态
     */
    public Map<String, Object> getKeyHealthStatus(Long teamId, Long userId) {
        logger.info("🏥 检查团队密钥健康状态: teamId={}, userId={}", teamId, userId);

        // 验证用户是否为团队成员
        if (!teamMemberService.isTeamMember(teamId, userId)) {
            throw new BusinessException("您不是该团队成员，无法查看密钥状态");
        }

        Map<String, Object> healthStatus = new HashMap<>();

        Optional<TeamKey> currentKeyOpt = teamKeyRepository.findCurrentActiveKey(teamId);
        
        if (currentKeyOpt.isEmpty()) {
            healthStatus.put("healthy", false);
            healthStatus.put("status", "NO_KEY");
            healthStatus.put("message", "团队密钥不存在");
            healthStatus.put("recommendation", "需要初始化团队密钥");
        } else {
            TeamKey currentKey = currentKeyOpt.get();
            boolean isExpired = isKeyExpired(currentKey);
            boolean isExpiringSoon = isKeyExpiringSoon(currentKey, 7); // 7天内过期

            healthStatus.put("healthy", !isExpired);
            healthStatus.put("keyVersion", currentKey.getKeyVersion());
            healthStatus.put("algorithm", currentKey.getAlgorithm());
            healthStatus.put("keyLength", currentKey.getKeyLength());
            healthStatus.put("createdAt", currentKey.getCreatedAt());
            healthStatus.put("expiresAt", currentKey.getExpiresAt());
            healthStatus.put("isExpired", isExpired);
            healthStatus.put("isExpiringSoon", isExpiringSoon);

            if (isExpired) {
                healthStatus.put("status", "EXPIRED");
                healthStatus.put("message", "密钥已过期");
                healthStatus.put("recommendation", "需要立即轮换密钥");
            } else if (isExpiringSoon) {
                healthStatus.put("status", "EXPIRING_SOON");
                healthStatus.put("message", "密钥即将过期");
                healthStatus.put("recommendation", "建议尽快轮换密钥");
            } else {
                healthStatus.put("status", "HEALTHY");
                healthStatus.put("message", "密钥状态正常");
                healthStatus.put("recommendation", "无需操作");
            }
        }

        healthStatus.put("checkTime", System.currentTimeMillis());
        
        logger.info("✅ 密钥健康检查完成: teamId={}, status={}", teamId, healthStatus.get("status"));
        return healthStatus;
    }

    /**
     * 获取密钥统计信息
     */
    public Map<String, Object> getKeyStatistics(Long teamId, Long userId) {
        logger.info("📊 获取团队密钥统计: teamId={}, userId={}", teamId, userId);

        // 验证用户是否为团队成员
        if (!teamMemberService.isTeamMember(teamId, userId)) {
            throw new BusinessException("您不是该团队成员，无法查看密钥统计");
        }

        Map<String, Object> stats = new HashMap<>();

        // 基本统计
        long totalKeys = teamKeyRepository.countByTeamId(teamId);
        long activeKeys = teamKeyRepository.countActiveKeysByTeamId(teamId);
        Integer maxVersion = teamKeyRepository.findMaxKeyVersion(teamId);

        stats.put("totalKeys", totalKeys);
        stats.put("activeKeys", activeKeys);
        stats.put("maxKeyVersion", maxVersion != null ? maxVersion : 0);

        // 状态统计
        List<Object[]> statusCounts = teamKeyRepository.countKeysByStatus(teamId);
        Map<String, Long> statusMap = new HashMap<>();
        for (Object[] row : statusCounts) {
            statusMap.put(row[0].toString(), (Long) row[1]);
        }
        stats.put("statusCounts", statusMap);

        // 当前密钥信息
        Optional<TeamKey> currentKeyOpt = teamKeyRepository.findCurrentActiveKey(teamId);
        if (currentKeyOpt.isPresent()) {
            TeamKey currentKey = currentKeyOpt.get();
            stats.put("currentKeyVersion", currentKey.getKeyVersion());
            stats.put("currentKeyCreatedAt", currentKey.getCreatedAt());
            stats.put("currentKeyExpiresAt", currentKey.getExpiresAt());
        }

        logger.info("✅ 密钥统计获取完成: teamId={}, totalKeys={}", teamId, totalKeys);
        return stats;
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 生成安全密钥
     */
    private String generateSecureKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
            keyGenerator.init(KEY_LENGTH, new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (NoSuchAlgorithmException e) {
            logger.error("❌ 密钥生成失败: {}", e.getMessage(), e);
            throw new BusinessException("密钥生成失败: " + e.getMessage());
        }
    }

    /**
     * 检查密钥是否过期
     */
    private boolean isKeyExpired(TeamKey teamKey) {
        if (teamKey.getExpiresAt() == null) {
            return false; // 永不过期
        }
        return LocalDateTime.now().isAfter(teamKey.getExpiresAt());
    }

    /**
     * 检查密钥是否即将过期
     */
    private boolean isKeyExpiringSoon(TeamKey teamKey, int daysThreshold) {
        if (teamKey.getExpiresAt() == null) {
            return false; // 永不过期
        }
        return LocalDateTime.now().plusDays(daysThreshold).isAfter(teamKey.getExpiresAt());
    }

    /**
     * 转换实体为DTO
     */
    private TeamKeyDTO convertToDTO(TeamKey teamKey) {
        TeamKeyDTO dto = new TeamKeyDTO();
        dto.setId(teamKey.getId());
        dto.setTeamId(teamKey.getTeamId());
        dto.setKeyVersion(teamKey.getKeyVersion());
        dto.setEncryptedKey(teamKey.getEncryptedKey());
        dto.setAlgorithm(teamKey.getAlgorithm());
        dto.setKeyLength(teamKey.getKeyLength());
        dto.setStatus(teamKey.getStatus().name());
        dto.setCreatedBy(teamKey.getCreatedBy());

        // 获取创建者信息
        User creator = userRepository.findById(teamKey.getCreatedBy()).orElse(null);
        if (creator != null) {
            dto.setCreatorName(creator.getUsername());
        }

        // 时间转换
        if (teamKey.getExpiresAt() != null) {
            dto.setExpiresAt(teamKey.getExpiresAt().toEpochSecond(java.time.ZoneOffset.UTC) * 1000);
        }
        dto.setCreatedAt(teamKey.getCreatedAt().toEpochSecond(java.time.ZoneOffset.UTC) * 1000);
        dto.setUpdatedAt(teamKey.getUpdatedAt().toEpochSecond(java.time.ZoneOffset.UTC) * 1000);

        return dto;
    }
}
